//This example show how to access CvSeq Element and show how to apply CvSeq from source picture. 
//it's similar to Demo.java , but only test on short of image .Also it show the results of each function.

package test;

import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.cpp.opencv_core.CvSeq;

import static com.googlecode.javacpp.Loader.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;

public class HandInOneShotDetector {
	public static void main(String args[]) {
		CvMemStorage mem = cvCreateMemStorage(0);

		CvSeq squares = new CvContour();
		squares = cvCreateSeq(0, sizeof(CvContour.class), sizeof(CvSeq.class),
				mem);
		String path = "C:/Documents and Settings/Administrator/workspace/HandRecognition/src/test/handhole.png";
		IplImage src_image = cvLoadImage(path);
		IplImage grey = cvCreateImage(cvGetSize(src_image), IPL_DEPTH_8U, 1);
		;

		cvCvtColor(src_image, grey, CV_BGR2GRAY);
		cvFindContours(grey, mem, squares, Loader.sizeof(CvContour.class),
				CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

		// squares = cvApproxPoly(squares, sizeof(CvContour.class), mem,
		// CV_POLY_APPROX_DP, cvContourPerimeter(squares)*0.02, 0);
		// CvSeq ss=null;

		cvDrawContours(src_image, squares, CvScalar.MAGENTA,
				CV_RGB(248, 18, 18), 1, -1, 8);

		System.out.println("Square net.:" + squares.total());

		// Finding SeqSquare

		CvSeq hull_seq = new CvSeq(null);
		// defect_seq = cvCreateSeq(arg0, arg1, arg2, arg3);
		hull_seq = cvConvexHull2(squares, null, CV_CLOCKWISE, 0);

		CvRect rect = cvBoundingRect(squares, 0);
		cvRectangle(src_image, cvPoint(rect.x(), rect.y() + rect.height()),
				cvPoint(rect.x() + rect.width(), rect.y()),
				CV_RGB(200, 0, 200), 5, 8, 0);

		// CvMat pointMatrix = cvMat(1, squares.total(), CV_32SC2, pointArray);
		CvMat hullMatrix = cvCreateMat(1, squares.total(), CV_32SC1);
		CvMat squareMatrix = cvCreateMat(1, squares.total(), CV_32SC1);
		CvMat defectMatrix = cvCreateMat(1, squares.total(), CV_32SC1);

		// Draw Hull

		CvPoint pointArray = new CvPoint(squares.total());
		cvCvtSeqToArray(squares, pointArray, CV_WHOLE_SEQ);
		cvConvexHull2(squares, hullMatrix, CV_COUNTER_CLOCKWISE, 0);

		int hullCount = hullMatrix.cols();
		System.out.println("Hull Pos net.:" + hullCount);
		CvPoint pt = pointArray.position((int) hullMatrix.get(hullCount - 1));

		CvPoint pt0 = new CvPoint(pt.x(), pt.y());
		for (int i = 0; i < hullCount; i++) {
			pt = pointArray.position((int) hullMatrix.get(i));

			System.out.println("@Position (" + i + ") >>" + hullMatrix.get(i)
					+ ":Point: X-" + pt.x() + ":Y-" + pt.y());
			cvLine(src_image, pt0, pt, CV_RGB(255, 255, 0), 3, CV_AA, 0);
			pt0 = new CvPoint(pt.x(), pt.y());
		}

		System.out.println(hullMatrix.cols());

		// Draw defect
		CvMemStorage defectStr;
		defectStr = cvCreateMemStorage(0);
		CvSeq defect_seq = cvConvexityDefects(squares, hullMatrix, defectStr);

		CvConvexityDefect defectArray = new CvConvexityDefect(
				defect_seq.total()); // create ConvexityDefectArray with
										// defect_size
		cvCvtSeqToArray(defect_seq, defectArray, CV_WHOLE_SEQ);// convert to
																// CvconvextDefect
																// , Array

		// Store defect
		// http://forum.openframeworks.cc/index.php?topic=850.0
		int defectCount = defect_seq.total();

		for (int j = 0; j < defectCount; j++) {
			CvPoint v = new CvPoint(cvGetSeqElem(defect_seq, j));
			System.out.println(defect_seq);
			System.out.println("P." + j + " X value = " + v.x() + " ; "
					+ "Y value = " + v.y());
		}

		CvPoint pointArray2 = new CvPoint(defectCount);
		for (int i = 0; i < defectCount; i++) {

			System.out.println("Defect@Round " + i + ":" + "start p"
					+ defectArray.position(i).start() + ", Dept p"
					+ defectArray.position(i).depth_point() + ", end p"
					+ defectArray.position(i).end() + ", dept:"
					+ defectArray.position(i).depth());
			cvLine(src_image, defectArray.position(i).start(), defectArray
					.position(i).depth_point(), CV_RGB(0, 0, 255), 1, CV_AA, 0);
			cvDrawCircle(src_image, defectArray.position(i).start(), 5,
					CvScalar.GREEN, -1, 8, 0);
			cvDrawCircle(src_image, defectArray.position(i).depth_point(), 5,
					CvScalar.GREEN, -1, 8, 0);
			cvLine(src_image, defectArray.position(i).depth_point(),
					defectArray.position(i).end(), CV_RGB(0, 0, 255), 1, CV_AA,
					0);

			// delete some no need defectPoint , to find exact defect point
			CvConvexityDefect newDefectArray;
			if (!defectArray.isNull()) {
				newDefectArray = new CvConvexityDefect();

				double minimumDepth = 20.0;
				for (int j = 0; j < defectCount; j++) {
					if (defectArray.position(i).depth() < minimumDepth) {
						break;
					}

				}
			}
		}

		// if(!ss.isNull()){
		// drawPoly(src_image, squares);
		// }
		final CanvasFrame canvas = new CanvasFrame("Point Identify");
		canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
		canvas.showImage(src_image);

		cvReleaseMemStorage(mem);
		cvReleaseMemStorage(defectStr);

	}

	public static CvSeq getExactDefect(CvSeq defectSeq) {
		CvSeq newDefSeq;
		CvMemStorage mem;

		if (defectSeq.isNull()) {
			System.out.println("DefectSeq Not found");

			return null;
		}
		mem = cvCreateMemStorage(0);
		newDefSeq = cvCreateSeq(0, Loader.sizeof(CvConvexityDefect.class),
				Loader.sizeof(CvSeq.class), mem);
		return defectSeq;
	}

	public static void drawPoly(IplImage src_im, CvSeq poly) {
		CvSeq rslt = cvApproxPoly(poly, Loader.sizeof(CvContour.class),
				cvCreateMemStorage(0), CV_POLY_APPROX_DP,
				cvContourPerimeter(poly) * 0.02, 0);
		System.out.println("2nd ApproxPoly net.: " + rslt.total());
		for (int i = 0; i < rslt.total(); i++) {
			CvPoint v = new CvPoint(cvGetSeqElem(rslt, i));
			cvDrawCircle(src_im, v, 5, CvScalar.BLUE, -1, 8, 0);
			System.out.println(" X value = " + v.x() + " ; Y value =" + v.y());
		}

	}

}
